import asyncio
import logging
import threading
import time
import requests
import uvicorn
from typing import Dict, Optional
from fastapi import FastAPI
from app.core.config import settings

logger = logging.getLogger(__name__)

# 全局变量存储当前任务参数
_current_job_param = None
_job_param_lock = threading.Lock()


class XXLJobExecutor:
    """XXL-Job执行器"""
    
    def __init__(self, main_app: FastAPI):
        self.main_app = main_app
        self.executor_app = FastAPI(title="XXL-Job Executor")
        self.app_name = settings.XXL_JOB_EXECUTOR_APP_NAME
        self.port = settings.XXL_JOB_EXECUTOR_PORT
        self.access_token = settings.XXL_JOB_ACCESS_TOKEN
        self.admin_addresses = [settings.XXL_JOB_ADMIN_URL]
        
        # 自动注册相关属性
        self.is_registered = False
        self.heartbeat_task = None
        self.registry_thread = None
        self.stop_event = threading.Event()
        self.server_thread = None
        
        # 注册执行器端点
        self._register_endpoints()
        
        # 启动执行器服务器
        self._start_executor_server()
        
        # 根据配置启动自动注册
        if settings.XXL_JOB_AUTO_REGISTRY:
            self._start_auto_registry()
            logger.info("XXL-Job auto registry enabled")
        else:
            logger.info("XXL-Job auto registry disabled, using manual registration")
    
    def _register_endpoints(self):
        """注册执行器API端点"""
        
        @self.executor_app.post("/xxl-job/beat")
        async def beat():
            """心跳检测"""
            return {
                "code": 200,
                "msg": "success"
            }
        
        @self.executor_app.post("/xxl-job/idleBeat")
        async def idle_beat(request_data: dict):
            """空闲检测"""
            return {
                "code": 200,
                "msg": "success"
            }
        
        @self.executor_app.post("/xxl-job/run")
        async def run(request_data: dict):
            """执行任务"""
            try:
                job_id = request_data.get('jobId')
                executor_handler = request_data.get('executorHandler')
                executor_params = request_data.get('executorParams', '')
                
                logger.info(f"Executing job {job_id} with handler {executor_handler}")
                
                # 设置当前任务参数
                global _current_job_param
                with _job_param_lock:
                    _current_job_param = executor_params
                
                # 动态调用handler
                result = await self._execute_handler(executor_handler, executor_params)
                
                # 清除任务参数
                with _job_param_lock:
                    _current_job_param = None
                
                if result.get('success', False):
                    return {
                        "code": 200,
                        "msg": result.get('message', 'success')
                    }
                else:
                    return {
                        "code": 500,
                        "msg": result.get('message', 'execution failed')
                    }
                    
            except Exception as e:
                logger.error(f"Error executing job: {e}")
                return {
                    "code": 500,
                    "msg": str(e)
                }
        
        @self.executor_app.post("/xxl-job/kill")
        async def kill(request_data: dict):
            """终止任务"""
            job_id = request_data.get('jobId')
            logger.info(f"Killing job {job_id}")
            
            # TODO: 实现任务终止逻辑
            return {
                "code": 200,
                "msg": "success"
            }
        
        @self.executor_app.post("/xxl-job/log")
        async def log(request_data: dict):
            """获取任务日志"""
            return {
                "code": 200,
                "msg": "success",
                "content": {
                    "fromLineNum": 1,
                    "toLineNum": 1,
                    "logContent": "Task executed successfully",
                    "isEnd": True
                }
            }
    
    async def _execute_handler(self, handler_name: str, params: str) -> Dict:
        """执行具体的handler"""
        try:
            # 导入handler模块
            from app.xxl_job.handler import get_handler
            
            handler_func = get_handler(handler_name)
            if not handler_func:
                return {
                    "success": False,
                    "message": f"Handler '{handler_name}' not found"
                }
            
            # 执行handler
            if asyncio.iscoroutinefunction(handler_func):
                result = await handler_func(params)
            else:
                # 在线程池中执行同步函数
                loop = asyncio.get_event_loop()
                result = await loop.run_in_executor(None, handler_func, params)
            
            return result if isinstance(result, dict) else {"success": True, "message": "completed"}
            
        except Exception as e:
            logger.error(f"Error executing handler {handler_name}: {e}")
            return {
                "success": False,
                "message": str(e)
            }
    
    def _start_executor_server(self):
        """启动执行器服务器"""
        def run_server():
            uvicorn.run(
                self.executor_app,
                host="0.0.0.0",
                port=self.port,
                log_level="info"
            )
        
        self.server_thread = threading.Thread(target=run_server, daemon=True)
        self.server_thread.start()
        logger.info(f"XXL-Job executor server started on port {self.port}")
        
        # 等待服务器启动完成
        time.sleep(3)
        logger.info("XXL-Job executor server startup completed")
    
    def get_registry_info(self) -> Dict:
        """获取执行器注册信息"""
        return {
            "registryGroup": "EXECUTOR",
            "registryKey": self.app_name,
            "registryValue": f"http://localhost:{self.port}"
        }
    
    def _start_auto_registry(self):
        """启动自动注册线程"""
        def delayed_start():
            # 等待执行器服务器完全启动后再开始注册
            time.sleep(5)
            logger.info("Starting auto registry worker...")
            self._registry_worker()
        
        self.registry_thread = threading.Thread(target=delayed_start, daemon=True)
        self.registry_thread.start()
        logger.info("Auto registry thread started")
    
    def _registry_worker(self):
        """注册工作线程"""
        while not self.stop_event.is_set():
            try:
                if not self.is_registered:
                    self._register_executor()
                else:
                    self._send_heartbeat()
                
                # 每30秒发送一次心跳
                self.stop_event.wait(30)
                
            except Exception as e:
                logger.error(f"Registry worker error: {e}")
                self.is_registered = False
                self.stop_event.wait(10)  # 出错后等待10秒重试
    
    def _register_executor(self):
        """向调度中心注册执行器"""
        try:
            registry_url = f"{self.admin_addresses[0]}/api/registry"
            registry_value = f"http://{settings.XXL_JOB_EXECUTOR_HOST}:{self.port}"
            registry_data = {
                "registryGroup": "EXECUTOR",
                "registryKey": self.app_name,
                "registryValue": registry_value
            }
            
            logger.info(f"Registering executor with address: {registry_value}")
            logger.info(f"Registry URL: {registry_url}")
            logger.info(f"Registry data: {registry_data}")
            
            headers = {
                "Content-Type": "application/json",
                "XXL-JOB-ACCESS-TOKEN": self.access_token
            }
            
            response = requests.post(
                registry_url,
                json=registry_data,
                headers=headers,
                timeout=10
            )
            
            if response.status_code == 200:
                result = response.json()
                if result.get("code") == 200:
                    self.is_registered = True
                    logger.info(f"Executor registered successfully: {self.app_name}")
                else:
                    logger.error(f"Registration failed: {result.get('msg', 'Unknown error')}")
            else:
                logger.error(f"Registration request failed: {response.status_code}")
                
        except Exception as e:
            logger.error(f"Failed to register executor: {e}")
    
    def _send_heartbeat(self):
        """发送心跳"""
        try:
            registry_url = f"{self.admin_addresses[0]}/api/registryRemove"
            registry_data = {
                "registryGroup": "EXECUTOR",
                "registryKey": self.app_name,
                "registryValue": f"http://localhost:{self.port}"
            }
            
            headers = {
                "Content-Type": "application/json",
                "XXL-JOB-ACCESS-TOKEN": self.access_token
            }
            
            # 先移除再注册，模拟心跳
            requests.post(
                registry_url,
                json=registry_data,
                headers=headers,
                timeout=5
            )
            
            # 重新注册
            self._register_executor()
            
        except Exception as e:
            logger.error(f"Failed to send heartbeat: {e}")
            self.is_registered = False
    
    def stop_registry(self):
        """停止自动注册和执行器服务器"""
        if self.registry_thread and self.registry_thread.is_alive():
            self.stop_event.set()
            self.registry_thread.join(timeout=5)
            
            # 注销执行器
            self._unregister_executor()
            
            logger.info("Auto registry stopped")
        
        # 注意：执行器服务器会在主进程结束时自动停止（daemon线程）
        logger.info("Executor server will stop with main process")
    
    def _unregister_executor(self):
        """注销执行器"""
        try:
            registry_url = f"{self.admin_addresses[0]}/api/registryRemove"
            registry_data = {
                "registryGroup": "EXECUTOR",
                "registryKey": self.app_name,
                "registryValue": f"http://localhost:{self.port}"
            }
            
            headers = {
                "Content-Type": "application/json",
                "XXL-JOB-ACCESS-TOKEN": self.access_token
            }
            
            response = requests.post(
                registry_url,
                json=registry_data,
                headers=headers,
                timeout=10
            )
            
            if response.status_code == 200:
                logger.info(f"Executor unregistered successfully: {self.app_name}")
            else:
                logger.error(f"Unregistration failed: {response.status_code}")
                
        except Exception as e:
            logger.error(f"Failed to unregister executor: {e}")


def get_job_param() -> Optional[str]:
    """获取当前任务参数"""
    global _current_job_param
    with _job_param_lock:
        return _current_job_param


def set_job_param(param: str):
    """设置任务参数（用于测试）"""
    global _current_job_param
    with _job_param_lock:
        _current_job_param = param


# 全局执行器实例（在main.py中初始化）
xxl_job_executor = None


def init_executor(app: FastAPI) -> XXLJobExecutor:
    """初始化执行器"""
    global xxl_job_executor
    xxl_job_executor = XXLJobExecutor(app)
    return xxl_job_executor